package xj.model.uml;

import java.util.*;

import static xj.model.uml.UMLModelConstants.ROLE_DO_ACTION;
import static xj.model.uml.UMLModelConstants.ROLE_ENTRY_ACTION;
import static xj.model.uml.UMLModelConstants.ROLE_EXIT_ACTION;
import static xj.model.uml.UMLModelConstants.ATTR_TYPE;
import static xj.model.uml.UMLModelConstants.ROLE_INTERNAL_TRANSITION;

public class State 
  extends NamedElement {

  public static enum StateType {
      State_Machine,

      Simple_State, 
      Initial_State, 
      Final_State, 
      Shallow_History_State, 
      Deep_History_State, 
      Decision_State, 
      Junction_State, 
      Hyper_State, 
      Orthogonal_State, 
      Orthogonal_Region, 
      Submachine_State, 
      Entry_Point, 
      Exit_Point, 
      Terminate_Point,
  }

  public State() {
    this(null, StateType.Simple_State);
  }

  public State(String name) {
    this(name, StateType.Simple_State);
  }

  public State(StateType type) {
    this(null, type);
  }

  public State(String name, StateType type) {
    super(name);
    setType(type);

    internalTransitions = new ArrayList<InternalTransition>();
  }

  public StateType getType() {
    return type;
  }

  public void setType(StateType type) {
    this.type = type;
    setAttribute(ATTR_TYPE, type);

    destructable = (type == StateType.Hyper_State || 
		    type == StateType.State_Machine || 
		    type == StateType.Orthogonal_State || 
		    type == StateType.Orthogonal_Region);
  }

  public String getEntryActionBody() {
    if (entryAction != null) { 
      return entryAction.getBody();
    } else {
      return null;
    }
  }

  public void setEntryActionBody(String a) {
    if (entryAction == null) { 
      setEntryAction(new Action("entry", null, a));
    } else { 
      entryAction.setBody(a);
    }
  }

  public Action getEntryAction() {
    return entryAction;
  }

  public void setEntryAction(Action a) {
    entryAction = a;
    setOwnedElement(ROLE_ENTRY_ACTION, entryAction);
  }

  public String getExitActionBody() {
    if (exitAction != null) { 
      return exitAction.getBody();
    } else {
      return null;
    }
  }

  public void setExitActionBody(String a) {
    if (exitAction == null) { 
      setExitAction(new Action("exit", null, a));
    } else { 
      exitAction.setBody(a);
    }
  }

  public Action getExitAction() {
    return exitAction;
  }

  public void setExitAction(Action a) {
    exitAction = a;
    setOwnedElement(ROLE_EXIT_ACTION, exitAction);
  }


  public String getDoActionBody() {
    if (doAction != null) { 
      return doAction.getBody();
    } else {
      return null;
    }
  }

  public void setDoActionBody(String a) {
    if (doAction == null) { 
      setDoAction(new Action("do", null, a));
    } else { 
      doAction.setBody(a);
    }
  }

  public Action getDoAction() {
    return doAction;
  }

  public void setDoAction(Action a) {
    doAction = a;
    setOwnedElement(ROLE_DO_ACTION, doAction);
  }

  public List<InternalTransition> getInternalTransitions() {
    return internalTransitions;
  }

  public void addInternalTransition(InternalTransition f) {
    if (f != null) {
      internalTransitions.add(f);
      addOwnedElement(f, ROLE_INTERNAL_TRANSITION);
    }
  }

  public void removeInternalTransition(InternalTransition f) {
    if (f != null) {
      internalTransitions.remove(f);
      removeOwnedElement(f);
    }
  }

  public void removeAllInternalTransitions() {
    Iterator<InternalTransition> iter = internalTransitions.iterator();
    while (iter.hasNext()) {
      InternalTransition f = iter.next();
      removeOwnedElement(f);
      iter.remove();
    }
  }

  @Override
  public String toString() {
    return "State: name=" + name;
  }

  @Override
  public Object clone() throws CloneNotSupportedException {
    State s = (State) super.clone();
    s.setType(type);
    s.setEntryAction(entryAction);
    s.setExitAction(exitAction);
    s.setDoAction(doAction);

    s.internalTransitions = new ArrayList<InternalTransition>();
    Iterator<InternalTransition> iter = internalTransitions.iterator();
    while (iter.hasNext()) {
      InternalTransition t = iter.next();
      s.addInternalTransition((InternalTransition) t.clone());
    }
    return s;
  }

  protected StateType type;

  protected Action entryAction;

  protected Action exitAction;

  protected Action doAction;

  protected List<InternalTransition> internalTransitions;

}
